import asyncio
import json

from openai import OpenAI
from openai import AsyncOpenAI
from openai.lib.streaming._assistants import AsyncAssistantEventHandler
from openai.types.beta import VectorStore
from openai.types.beta.assistant import Assistant
from openai.types.beta.thread import Thread
from openai.types.beta.threads.run import Run
from typing_extensions import override

from llm.entity.dto.DeviceConfigAddDTO import DeviceConfigAddDTO
from llm.entity.metadatas import VectorStoreMetadata
from llm.service.DeviceService import DeviceService
from llm.prompt.OneNetPrompts import OneNetPrompt, OneNetParserPrompt

from llm.models import Assistants, Threads
from llm.entity.dao.AssistantsDAO import AssistantsDAO
from llm.entity.dao.VectorStoreDAO import VectorStoreDAO
from llm.service.OpenAIService import ConsumerFunctionEventHandler, FunctionEventHandler
from users.models import Users

client = OpenAI()
class RunService:
    @classmethod
    async def arun_with_func_consumer(cls, message: str, user_id: str, assistant_id: str, thread_id: str,
                                      consumer):
        """
        向线程发送消息，并运行智能家居助手（Assistant）,执行本地函数调用
        :param consumer:
        :param message:
        :param user_id:
        :param assistant_id:
        :param thread_id:
        :return:
        """
        client = AsyncOpenAI()
        message = await client.beta.threads.messages.create(
            thread_id=thread_id,
            content=message,
            metadata={
                'user_id': user_id,
                'target_assistant_id': assistant_id,
                'thread_id': thread_id
            },
            role='user'
        )
        async with client.beta.threads.runs.stream(
                thread_id=thread_id,
                assistant_id=assistant_id,
                event_handler=ConsumerFunctionEventHandler(consumer=consumer)
        ) as stream:
            await stream.until_done()

    @classmethod
    async def arun_with_func(cls, message: str, user_id: str, assistant_id: str, thread_id: str, ) -> Run:
        """

        :param message:
        :param user_id:
        :param assistant_id:
        :param thread_id:
        :return:
        """
        client = AsyncOpenAI()
        message = await client.beta.threads.messages.create(
            thread_id=thread_id,
            content=message,
            metadata={
                'user_id': user_id,
                'target_assistant_id': assistant_id,
                'thread_id': thread_id
            },
            role='user'
        )
        event_handler = FunctionEventHandler()
        async with client.beta.threads.runs.stream(
                thread_id=thread_id,
                assistant_id=assistant_id,
                event_handler=event_handler
        ) as stream:
            await stream.until_done()
        cur_run = await stream.get_final_run()
        # cancelled_run=await client.beta.threads.runs.cancel(
        #     thread_id=thread_id,
        #     run_id=cur_run.id
        # )
        return cur_run

    @classmethod
    async def aparse_command(cls, message: str, assistant_id: str, thread_id: str) -> str:
        """
        解析指令并执行并给出指令的解析结果
        :param message:
        :param user_id:
        :param assistant_id:
        :param thread_id:
        :param consumer:
        :return:
        """
        # client = AsyncOpenAI()
        # async with client.beta.threads.runs.stream(
        #         thread_id=thread_id,
        #         assistant_id=assistant_id,
        #         event_handler=OpenAIService.WebSocketOutputHandler(consumer=consumer)
        # ) as stream:
        #     await stream.until_done()

        client = AsyncOpenAI()
        message = await client.beta.threads.messages.create(
            thread_id=thread_id,
            content=message,
            role='user',
        )
        stream_run = await client.beta.threads.runs.create(
            thread_id=thread_id,
            assistant_id=assistant_id,
            stream=True,
        )

        latest_assistant_message: str = ''
        # async for event in stream_run:
        #     if not hasattr(event.data, 'status'):  # 检查事件数据是否有 'status' 属性
        #         if hasattr(event.data, 'delta') and event.data.delta:
        #             for block in event.data.delta.content:
        #                 text = block.text.value
        #                 latest_assistant_message = text
        #                 print(text, end="", flush=True)

        async for event in stream_run:
            if hasattr(event.data, 'status'):  # 检查事件数据是否有 'status' 属性
                pass
            else:
                # print(f"事件 ID: {event.data.id} 没有 status 属性。")
                if hasattr(event.data, 'delta') and event.data.delta:
                    if hasattr(event.data.delta, 'content') and event.data.delta.content:
                        for block in event.data.delta.content:
                            text = block.text.value
                            latest_assistant_message += text
                            # print(text.encode('utf-8', errors='ignore').decode('utf-8'), end="", flush=True)

        if latest_assistant_message != '':
            # print(f"最新的回复：{latest_assistant_message}")
            # 分解字符串为JSON数据交由后端去执行
            start_marker = "`json"
            end_marker = "`"
            start_index = latest_assistant_message.find(start_marker)
            end_index = None
            if start_index != -1:
                start_index += len(start_marker)
                end_index = latest_assistant_message.find(end_marker, start_index)

            if start_index != -1 and end_index != -1:
                parsed_message = latest_assistant_message[start_index:end_index].strip()
                print(f"解析出来的字符串：{parsed_message}")
                return parsed_message
            else:
                print(f"未找到JSON数据")
                return ""

    @classmethod
    async def cancel_run(cls, run_id, thread_id):
        client = AsyncOpenAI()
        cancelled_run = await client.beta.threads.runs.cancel(
            run_id=run_id,
            thread_id=thread_id
        )
        print(f"cancel_run:取消运行{run_id}成功")
        return cancelled_run